package com.shure.surdes.common.exception;

import com.mysql.cj.exceptions.AssertionFailedException;
import com.shure.surdes.common.result.R;
import com.shure.surdes.common.result.Result;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MissingRequestValueException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @ClassName GlobalExceptionHandler
 * @Description
 * @Author shure
 * @Date 2023/3/16 17:26
 * @Version 1.0
 **/

@RestControllerAdvice
@ControllerAdvice
@Order(Ordered.HIGHEST_PRECEDENCE)
@ResponseBody
@Slf4j
public class GlobalExceptionHandler {

    @ExceptionHandler(value = Exception.class)
    public R exceptionHandler(HttpServletRequest request, Exception e) {
        String url = request.getRequestURI();
        log.error("请求出错啦 - 请求的url - {}", url);

        //业务异常处理逻辑
        if (e instanceof ServeException) {
            log.error("[ ServeException ]：服务异常", e);
            return Result.error(((ServeException) e).getCodeMsg());
        }

        //token 失效异常
        //if (e instanceof NotLoginException) {
        //    log.error("[ NotLoginException ]：token 无效", e);
        //    return Result.error(401, "token 失效");
        //}

        //参数校验异常处理逻辑
        if (e instanceof BindException exception) {
            log.error("[ BindException ]：参数校验异常", e);
            List<ObjectError> errors = exception.getAllErrors();
            Set<String> msgs = errors.stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.toSet());
            return Result.error("部分参数不合法", msgs);
        }

        //不合法参数异常 IllegalArgumentException
        if (e instanceof IllegalArgumentException) {
            log.error("[ IllegalArgumentException ]：参数不合法", e);
            return Result.error(e.getMessage());
        }

        //断言异常
        if (e instanceof AssertionFailedException) {
            log.error("[ AssertionError ]：断言异常", e);
            return Result.error("缺失必要的参数：" + e.getMessage());
        }

        // 请求参数丢失异常
        if (e instanceof MissingRequestValueException) {
            log.error("[ MissingRequestValueException ]：请求参数丢失异常", e);
            MissingServletRequestParameterException exception = (MissingServletRequestParameterException) e;
            return Result.error("缺失必要的参数：" + exception.getParameterName());
        }

        //运行时异常处理逻辑
        if (e instanceof RuntimeException) {
            log.error("[ RuntimeException ]：运行时异常", e);
            return Result.error("服务出错啦！");
        }

        log.error("[ " + e.getClass().getName() + " ]：未知异常", e);
        return Result.error();
    }
}
